package vendas.web.action;

import gminet.infra.db.TransactionException;
import gminet.infra.toolkit.NumberToolkit;
import gminet.infra.web.WebException;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

import vendas.business.OrderBusiness;
import vendas.dto.CurrencyType;
import vendas.dto.Order;
import vendas.dto.OrderStatus;
import vendas.dto.PaymentStatus;
import vendas.dto.ReportOrder;
import vendas.dto.SellStatus;
import vendas.dto.User;

@ManagedBean(name = "reportAction")
@SessionScoped
public class ReportAction extends WebAction {

    private static final long serialVersionUID = -2877634054453058828L;

    private List<ReportOrder> reportOrders;

    public ReportAction() {
        super();
    }

    public String listReportOrders() throws WebException {

        verifyLogin();
        return "listReportOrders";
    }

    public List<ReportOrder> getReportOrders() throws WebException {
        if (this.reportOrders == null) {
            this.reportOrders = new ArrayList<ReportOrder>();
            try {
                int userId = getLocalUser().getId();
                List<Order> orders = OrderBusiness.findAll(userId, false);
                for (Order order : orders) {
                    ReportOrder theReportOrder = getReportOrder(order);
                    if (theReportOrder == null) {
                        theReportOrder = createReportOrder(order);
                        this.reportOrders.add(theReportOrder);
                    } else {
                        incrementReportOrder(theReportOrder, order);
                    }
                }
            } catch (TransactionException te) {
                throw new WebException(te);
            }
        }
        return this.reportOrders;
    }

    private ReportOrder getReportOrder(Order order) {

        User user = order.getUser();
        Date paymentDate = order.getPaymentDate();
        CurrencyType currencyType = order.getCurrencyType();
        boolean pendent = isPendent(order);
        //
        ReportOrder theReportOrder = null;
        for (ReportOrder reportOrder : this.reportOrders) {
            boolean equals = reportOrder.getUser().equals(user);
            if (paymentDate == null) {
                equals &= reportOrder.getPaymentDate() == null;
            } else {
                equals &= (reportOrder.getPaymentDate() != null && reportOrder.getPaymentDate().equals(paymentDate));
            }
            equals &= reportOrder.getCurrencyType().equals(currencyType);
            equals &= (reportOrder.isPendent() == pendent);
            if (equals) {
                theReportOrder = reportOrder;
                break;
            }
        }
        return theReportOrder;
    }

    private ReportOrder createReportOrder(Order order) {

        ReportOrder theReportOrder = new ReportOrder();
        theReportOrder.setUser(order.getUser());
        theReportOrder.setPaymentDate(order.getPaymentDate());
        theReportOrder.setCurrencyType(order.getCurrencyType());
        theReportOrder.setPendent(isPendent(order));
        theReportOrder.setCurrencyValue(order.getCurrencyValue());
        theReportOrder.setTotalBuyValue(order.getBuyValue());
        theReportOrder.setTotalShippingValue(order.getShippingValue());
        theReportOrder.setTotalTaxValue(order.getTaxValue());
        theReportOrder.setTotalSellValue(order.getSellValue());
        return theReportOrder;
    }

    private void incrementReportOrder(ReportOrder theReportOrder, Order order) {

        theReportOrder.setTotalBuyValue(theReportOrder.getTotalBuyValue() + order.getBuyValue());
        theReportOrder.setTotalShippingValue(theReportOrder.getTotalShippingValue() + order.getShippingValue());
        theReportOrder.setTotalTaxValue(theReportOrder.getTotalTaxValue() + order.getTaxValue());
        theReportOrder.setTotalSellValue(theReportOrder.getTotalSellValue() + order.getSellValue());
    }

    private boolean isPendent(Order order) {

        boolean pendent = !order.getStatus().equals(OrderStatus.SOLD);
        pendent |= !order.getPaymentStatus().equals(PaymentStatus.PAY);
        pendent |= !order.getSellStatus().equals(SellStatus.RECEIVE_PAYMENT);
        return pendent;
    }

    public void setReportOrders(List<ReportOrder> reportOrders) {
        this.reportOrders = reportOrders;
    }

    public void clearReportOrders() {
        setReportOrders(null);
    }

    public String getStringTotalBuy() throws WebException {

        int total = 0;
        for (ReportOrder item : getReportOrders()) {
            if (!item.isPendent()) {
                total += item.getTotalFinalBuyValue();
            }
        }
        return NumberToolkit.getStringFromDouble(total);
    }

    public String getStringTotalSell() throws WebException {

        int total = 0;
        for (ReportOrder item : getReportOrders()) {
            if (!item.isPendent()) {
                total += item.getTotalSellValue();
            }
        }
        return NumberToolkit.getStringFromDouble(total);
    }

    public String getStringTotalGain() throws WebException {

        int total = 0;
        for (ReportOrder item : getReportOrders()) {
            if (!item.isPendent()) {
                total += item.getTotalGainValue();
            }
        }
        return NumberToolkit.getStringFromDouble(total);
    }

}
